package com.fcat.springboot.mybatis.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.fcat.base.common.util.StrUtil;
import com.github.pagehelper.PageHelper;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import tk.mybatis.spring.annotation.MapperScan;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Properties;


@Configuration
@MapperScan(basePackages = "com.fcat.common.user.mapper", sqlSessionTemplateRef  = "masterSqlSessionTemplate")
public class MasterDataSourceConfiguration  implements EnvironmentAware {

    private String driveClassName;
    private String url;
    private String userName;
    private String password;
    private String xmlLocation;
    private String typeAliasesPackage;
    /////////////////////druid参数///////////////////////////////////////////////////
    private String filters;
    private String maxActive;
    private String initialSize;
    private String maxWait;
    private String minIdle;
    private String timeBetweenEvictionRunsMillis;
    private String minEvictableIdleTimeMillis;
    private String validationQuery;
    private String testWhileIdle;
    private String testOnBorrow;
    private String testOnReturn;
    private String poolPreparedStatements;
    private String maxOpenPreparedStatements;
    //////////////////////////////////////////////////////////////////////////

    @Bean(name = "masterDataSource")
    @Primary
    public DataSource dataSource() {

        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(userName);
        druidDataSource.setPassword(password);
        druidDataSource.setDriverClassName(!StrUtil.isEmpty(driveClassName) ? driveClassName : "com.mysql.jdbc.Driver");
        druidDataSource.setMaxActive(!StrUtil.isEmpty(maxActive) ? Integer.parseInt(maxActive) : 10);
        druidDataSource.setInitialSize(!StrUtil.isEmpty(initialSize) ? Integer.parseInt(initialSize) : 1);
        druidDataSource.setMaxWait(!StrUtil.isEmpty(maxWait) ? Integer.parseInt(maxWait) : 60000);
        druidDataSource.setMinIdle(!StrUtil.isEmpty(minIdle) ? Integer.parseInt(minIdle) : 3);
        druidDataSource.setTimeBetweenEvictionRunsMillis(!StrUtil.isEmpty(timeBetweenEvictionRunsMillis) ?
                Integer.parseInt(timeBetweenEvictionRunsMillis) : 60000);
        druidDataSource.setMinEvictableIdleTimeMillis(!StrUtil.isEmpty(minEvictableIdleTimeMillis) ?
                Integer.parseInt(minEvictableIdleTimeMillis) : 300000);
        druidDataSource.setValidationQuery(!StrUtil.isEmpty(validationQuery) ? validationQuery : "select 'x'");
        druidDataSource.setTestWhileIdle(!StrUtil.isEmpty(testWhileIdle) ? Boolean.parseBoolean(testWhileIdle) : true);
        druidDataSource.setTestOnBorrow(!StrUtil.isEmpty(testOnBorrow) ? Boolean.parseBoolean(testOnBorrow) : false);
        druidDataSource.setTestOnReturn(!StrUtil.isEmpty(testOnReturn) ? Boolean.parseBoolean(testOnReturn) : false);
        druidDataSource.setPoolPreparedStatements(!StrUtil.isEmpty(poolPreparedStatements) ? Boolean.parseBoolean(poolPreparedStatements) : true);
        druidDataSource.setMaxOpenPreparedStatements(!StrUtil.isEmpty(maxOpenPreparedStatements) ? Integer.parseInt(maxOpenPreparedStatements) : 20);

        try {
            druidDataSource.setFilters(!StrUtil.isEmpty(filters) ? filters : "stat, wall");
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return druidDataSource;
    }

    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        if (!StrUtil.isEmpty(typeAliasesPackage)) {
            bean.setTypeAliasesPackage(typeAliasesPackage);
        }
        //分页插件
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("returnPageInfo", "check");
        properties.setProperty("params", "count=countSql");
        pageHelper.setProperties(properties);
        //添加XML目录
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Interceptor[] plugins = new Interceptor[]{pageHelper};
        bean.setPlugins(plugins);
        try {
            bean.setMapperLocations(resolver.getResources(xmlLocation));
            return bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "masterSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.url = environment.getProperty("spring.datasource.master.url");
        this.userName = environment.getProperty("spring.datasource.master.username");
        this.password = environment.getProperty("spring.datasource.master.password");
        this.driveClassName = environment.getProperty("spring.datasource.master.driver-class-name");
        this.filters = environment.getProperty("spring.datasource.master.filters");
        this.maxActive = environment.getProperty("spring.datasource.master.maxActive");
        this.initialSize = environment.getProperty("spring.datasource.master.initialSize");
        this.maxWait = environment.getProperty("spring.datasource.master.maxWait");
        this.minIdle = environment.getProperty("spring.datasource.master.minIdle");
        this.timeBetweenEvictionRunsMillis = environment.getProperty("spring.datasource.master.timeBetweenEvictionRunsMillis");
        this.minEvictableIdleTimeMillis = environment.getProperty("spring.datasource.master.minEvictableIdleTimeMillis");
        this.validationQuery = environment.getProperty("spring.datasource.master.validationQuery");
        this.testWhileIdle = environment.getProperty("spring.datasource.master.testWhileIdle");
        this.testOnBorrow = environment.getProperty("spring.datasource.master.testOnBorrow");
        this.testOnReturn = environment.getProperty("spring.datasource.master.testOnReturn");
        this.poolPreparedStatements = environment.getProperty("spring.datasource.master.poolPreparedStatements");
        this.maxOpenPreparedStatements = environment.getProperty("spring.datasource.master.maxOpenPreparedStatements");
        this.typeAliasesPackage = environment.getProperty("mybatis.master.typeAliasesPackage");
        this.xmlLocation = environment.getProperty("mybatis.master.xmlLocation");
    }
}